#include "replacer/clock_replacer.h"

#include <algorithm>

ClockReplacer::ClockReplacer(size_t num_pages)
    : circular_{num_pages, ClockReplacer::Status::EMPTY_OR_PINNED}, hand_{0}, capacity_{num_pages} {
    // 成员初始化列表语法
    circular_.reserve(num_pages);
}

ClockReplacer::~ClockReplacer() = default;

bool ClockReplacer::Victim(frame_id_t *frame_id) {
    const std::lock_guard<mutex_t> guard(mutex_);
    // Todo: try to find a victim frame in buffer pool with clock scheme
    // and make the *frame_id = victim_frame_id
    // not found, frame_id=nullptr and return false
    frame_id_t fuben=hand_;// 复制当前的hand_值，以备后面使用
    bool flag=false;// 复制当前的hand_值，以备后面使用
    while(true)// 复制当前的hand_值，以备后面使用
    {
        hand_++;// 递增hand_，并确保循环
        hand_=hand_%ClockReplacer::capacity_;
        if(fuben==hand_&&!flag)// 如果hand_回到了原始位置，并且尚未绕一圈，返回false
        {
            frame_id=nullptr;
            return false;
        }
        if(circular_[hand_]==Status::UNTOUCHED)// 如果当前frame为UNTOUCHED，表示可以作为victim
        {
            flag=true;
            *frame_id=hand_;
            circular_[hand_]=Status::EMPTY_OR_PINNED;
            return true;
        }
        else if(circular_[hand_]==Status::ACCESSED)// 如果当前frame为ACCESSED，将其标记为UNTOUCHED
        {
            flag=true;
            circular_[hand_]=Status::UNTOUCHED;
        }
    }
}

void ClockReplacer::Pin(frame_id_t frame_id) {
    const std::lock_guard<mutex_t> guard(mutex_);
    // Todo: you can implement it!
    if(frame_id < 0 || frame_id >= (int)capacity_ || circular_[frame_id] == Status::EMPTY_OR_PINNED)// 检查frame_id是否有效，以及它是否处于状态EMPTY_OR_PINNED
    {
        return;// 无效的frame_id或已经被固定，无需更改状态
    }
    else
    {
        circular_[frame_id] = Status::EMPTY_OR_PINNED;// 将frame的状态标记为EMPTY_OR_PINNED，表示已被固定
    }
}

void ClockReplacer::Unpin(frame_id_t frame_id) {
    const std::lock_guard<mutex_t> guard(mutex_);
    // Todo: you can implement it!
    if(frame_id < 0 || frame_id >= (int)capacity_ || circular_[frame_id] != Status::EMPTY_OR_PINNED)// 检查frame_id是否有效，以及它是否处于状态EMPTY_OR_PINNED
    {
        return;// 无效的frame_id或未被固定，无需更改状态
    }
    else
    {
        circular_[frame_id] = Status::ACCESSED;// 将frame的状态标记为ACCESSED，表示可以成为victim
    }
}

size_t ClockReplacer::Size() {
    // Todo:
    // 返回在[arg0, arg1)范围内满足特定条件(arg2)的元素的数目
    // return all items that in the range[circular_.begin, circular_.end )
    // and be met the condition: status!=EMPTY_OR_PINNED
    // That is the number of frames in the buffer pool that storage page (NOT EMPTY_OR_PINNED)
    size_t size = 0;
    auto it = circular_.begin();// 使用迭代器遍历circular_列表
    while(it != circular_.end())
    {
        if(*it != Status::EMPTY_OR_PINNED)// 如果frame的状态不等于EMPTY_OR_PINNED，增加size计数
        {
            size++;
        }
        ++it;
    }
    return size;// 返回能够成为victim的frame数量
}
